/**
 * @file
 * @author dousha 
 * @date 2020/6/12.
 */

#ifndef SKYLAB_GPIO_H
#define SKYLAB_GPIO_H

#include <stdint.h>

#include "peripheral.h"

/**
 * GPIO 引脚状态
 */
typedef enum {
	/// 低电平
	LOW,
	/// 高电平
	HIGH,
	/// 高阻抗
	HIGH_Z,
	/// 地
	GROUND,
	/// 源
	SOURCE,
} GpioState;

/**
 * GPIO 输入模式
 * 
 * 并不是所有硬件都支持给定的输入模式。
 */
typedef enum {
	/// 浮动输入/高阻态
	INPUT_FLOATING,
	/// 模拟信号输入
	INPUT_ANALOG,
	/// 内部下拉
	INPUT_INTERNALLY_PULLED_DOWN,
	/// 内部上拉
	INPUT_INTERNALLY_PULLED_UP,
} GpioInputMode;

/**
 * GPIO 输出模式
 * 
 * 并不是所有硬件都支持给定的输出模式。
 */
typedef enum {
	/// 推挽输出
	OUTPUT_PUSH_AND_PULL,
	/// 漏极输出
	OUTPUT_OPEN_DRAIN,
	/// 集极输出
	OUTPUT_OPEN_COLLECTOR,
} GpioOutputMode;

/**
 * GPIO 中断触发模式
 * 
 * 并不是所有引脚都支持 GPIO 中断，也不是所有中断模式都受支持。
 */
typedef enum {
	/// 上升沿触发
	RISING_EDGE,
	/// 下降沿触发
	FALLING_EDGE,
	/// 边沿触发
	BOTH_EDGES,
	/// 高电平触发
	HIGH_LEVEL,
	/// 低电平触发
	LOW_LEVEL,
} GpioInterruptMode;

#define GPIO_A1 0x00010000u
#define GPIO_A2 0x00010001u
#define GPIO_A3 0x00010002u
#define GPIO_A4 0x00010003u
#define GPIO_A5 0x00010004u
#define GPIO_A6 0x00010005u
#define GPIO_A7 0x00010006u
#define GPIO_A8 0x00010007u
#define GPIO_A9 0x00010008u
#define GPIO_A10 0x00010009u
#define GPIO_A11 0x0001000au
#define GPIO_A12 0x0001000bu
#define GPIO_A13 0x0001000cu
#define GPIO_A14 0x0001000du
#define GPIO_A15 0x0001000eu
#define GPIO_A16 0x0001000fu

#define GPIO_B1 0x00020000u
#define GPIO_B2 0x00020001u
#define GPIO_B3 0x00020002u
#define GPIO_B4 0x00020003u
#define GPIO_B5 0x00020004u
#define GPIO_B6 0x00020005u
#define GPIO_B7 0x00020006u
#define GPIO_B8 0x00020007u
#define GPIO_B9 0x00020008u
#define GPIO_B10 0x00020009u
#define GPIO_B11 0x0002000au
#define GPIO_B12 0x0002000bu
#define GPIO_B13 0x0002000cu
#define GPIO_B14 0x0002000du
#define GPIO_B15 0x0002000eu
#define GPIO_B16 0x0002000fu

#define GPIO_C1 0x00030000u
#define GPIO_C2 0x00030001u
#define GPIO_C3 0x00030002u
#define GPIO_C4 0x00030003u
#define GPIO_C5 0x00030004u
#define GPIO_C6 0x00030005u
#define GPIO_C7 0x00030006u
#define GPIO_C8 0x00030007u
#define GPIO_C9 0x00030008u
#define GPIO_C10 0x00030009u
#define GPIO_C11 0x0003000au
#define GPIO_C12 0x0003000bu
#define GPIO_C13 0x0003000cu
#define GPIO_C14 0x0003000du
#define GPIO_C15 0x0003000eu
#define GPIO_C16 0x0003000fu

#define GPIO_D1 0x00040000u
#define GPIO_D2 0x00040001u
#define GPIO_D3 0x00040002u
#define GPIO_D4 0x00040003u
#define GPIO_D5 0x00040004u
#define GPIO_D6 0x00040005u
#define GPIO_D7 0x00040006u
#define GPIO_D8 0x00040007u
#define GPIO_D9 0x00040008u
#define GPIO_D10 0x00040009u
#define GPIO_D11 0x0004000au
#define GPIO_D12 0x0004000bu
#define GPIO_D13 0x0004000cu
#define GPIO_D14 0x0004000du
#define GPIO_D15 0x0004000eu
#define GPIO_D16 0x0004000fu

#define GPIO_E1 0x00050000u
#define GPIO_E2 0x00050001u
#define GPIO_E3 0x00050002u
#define GPIO_E4 0x00050003u
#define GPIO_E5 0x00050004u
#define GPIO_E6 0x00050005u
#define GPIO_E7 0x00050006u
#define GPIO_E8 0x00050007u
#define GPIO_E9 0x00050008u
#define GPIO_E10 0x00050009u
#define GPIO_E11 0x0005000au
#define GPIO_E12 0x0005000bu
#define GPIO_E13 0x0005000cu
#define GPIO_E14 0x0005000du
#define GPIO_E15 0x0005000eu
#define GPIO_E16 0x0005000fu

extern void gpio_init();

extern void gpio_as_input(PeripheralIdentifier, GpioInputMode);

extern void gpio_as_output(PeripheralIdentifier, GpioOutputMode);

extern void gpio_set_interrupt(PeripheralIdentifier, GpioInterruptMode);

extern GpioState gpio_read(PeripheralIdentifier);

extern void gpio_write(PeripheralIdentifier, GpioState);

#endif //SKYLAB_GPIO_H
